﻿// -----------------------------------------------------------------------
// <copyright file="Playback.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Core.Player
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    /// <summary>
    /// Contains player main commands
    /// </summary>
    public class Playback
    {
        /// <summary> Lock synchronization object. </summary>
        private static readonly object Padlock = new object();

        /// <summary> Stores the current instance of this class </summary>
        private static Playback instance = null;

        /// <summary> Main audio class </summary>
        private Core.Player.Audio.AudioPlayer audio;

        /// <summary> Main video class </summary>
        private Core.Player.Video.VideoPlayer video;

        /// <summary> Prevents a default instance of the Playback class from being created. </summary>
        private Playback()
        {
            // Default, is stopped...
            //Status.PlaybackStatus = Status.StatusEnum.Stopped;
        }

        /// <summary> Gets the current instance of this class (Singleton - Thread safety)... With double check! </summary>
        public static Playback Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (Padlock)
                    {
                        if (instance == null)
                        {
                            instance = new Playback();
                        }
                    }
                }

                return instance;
            }
        }

        /// <summary>
        /// Open media file
        /// </summary>
        /// <param name="file">The file name to open</param>
        /// <returns>Returns the type of the file</returns>
        public Helper.FileTypeEnum Open(string file)
        {
            if (file != string.Empty)
            {
                // Stop playback if already playing
                if (Status.PlaybackStatus == Status.StatusEnum.Playing)
                {
                    this.Stop();
                }

                MediaInfo.CurrentFile = Helper.CheckFileType(file);

                // Returns apropiate object for this kind of file and play
                this.GetPlayerObject(MediaInfo.CurrentFile).Open(file, MediaInfo.CurrentFile);
            }

            return MediaInfo.CurrentFile;
        }

        /// <summary>
        /// Play media file
        /// </summary>
        public void Play()
        {
            // Call before open event
            if (Events.Instance.BeforeOpen != null)
            {
                Events.Instance.BeforeOpen(null, null);
            }

            if (Status.PlaybackStatus == Status.StatusEnum.Playing)
            {
                this.Stop();
            }

            // Returns apropiate object for this kind of file and play
            this.GetPlayerObject(MediaInfo.CurrentFile).Play();

            Status.PlaybackStatus = Status.StatusEnum.Playing;
        }

        /// <summary> Pause the current playback </summary>
        public void Pause()
        {
            // Returns apropiate object for this kind of file and pause playback
            this.GetPlayerObject(MediaInfo.CurrentFile).Pause();

            Status.PlaybackStatus = Status.StatusEnum.Paused;
        }

        /// <summary> Stop the current playback </summary>
        public void Stop()
        {
            // Returns apropiate object for this kind of file and stop playback
            this.GetPlayerObject(MediaInfo.CurrentFile).Stop();

            Status.PlaybackStatus = Status.StatusEnum.Stopped;
        }

        /// <summary> Resume the current playback </summary>
        public void Resume()
        {
            // Returns apropiate object for this kind of file and resume playback
            this.GetPlayerObject(MediaInfo.CurrentFile).Resume();

            Status.PlaybackStatus = Status.StatusEnum.Playing;
        }

        /// <summary>
        /// Seek to specified position
        /// </summary>
        /// <param name="value">Position to jump</param>
        public void Seek(int value)
        {
            this.GetPlayerObject(MediaInfo.CurrentFile).Seek(value);
        }

        /// <summary>
        /// Change volume
        /// </summary>
        /// <param name="value">Volume value</param>
        public void SetVolume(int value)
        {
            Status.Volume = value;
            this.GetPlayerObject(MediaInfo.CurrentFile).SetVolume(value);
        }

        /// <summary>
        /// Toggle video full screen mode
        /// </summary>
        public void SetVideoFullscreen()
        {
            this.GetPlayerObject(MediaInfo.CurrentFile).SetVideoFullscreen();
        }

        /// <summary>
        /// Factory stuff
        /// </summary>
        /// <param name="fileType">File type to open</param>
        /// <returns>Returns appropriate object to handle this type of file</returns>
        internal Player GetPlayerObject(Helper.FileTypeEnum fileType)
        {
            switch (fileType)
            {
                case Helper.FileTypeEnum.LocalAudio:
                    if (this.audio == null)
                    {
                        this.audio = new Audio.AudioPlayer();
                    }

                    return this.audio;
                case Helper.FileTypeEnum.LocalVideo:
                    if (this.video == null)
                    {
                        this.video = new Video.VideoPlayer();
                    }

                    return this.video;
                case Helper.FileTypeEnum.InternetAudioStream:
                    if (this.audio == null)
                    {
                        this.audio = new Audio.AudioPlayer();
                    }

                    return this.audio;
                default:
                    if (this.video == null)
                    {
                        this.video = new Video.VideoPlayer();
                    }

                    return this.video;
            }
        }
    }
}
